import type {
  LoadResult,
  PartialResolvedId,
  SourceDescription,
  PluginContext as RollupPluginContext,
  ResolvedId,

} from "rollup";
export interface PluginContainer {
  resolveId(id: string, importer?: string): Promise<PartialResolvedId | null>;
  load(id: string): Promise<LoadResult | null>;
  transform(code: string, id: string): Promise<SourceDescription | null>;
}
import { Plugin } from "./plugin";
export const createPluginContainer = (plugins: Plugin[]): PluginContainer => {
  class Context {
    async resolve(id: string, importer?: string) {
      let out = await pluginContainer.resolveId(id, importer);
      if (typeof out === "string") out = { id: out };
      return out as ResolvedId | null;
    }

  }

  const pluginContainer: PluginContainer = {
    async resolveId(id: string, importer?: string) {
      const ctx = new Context() as any;
      for (const plugin of plugins) {
        if (plugin.resolveId) {
          const newId = await plugin.resolveId.call(ctx, id, importer);
          if (newId) {
            id = typeof newId === "string" ? newId : newId.id;
            return { id }
          }
        }

      }
      return null
    },
    //插件机制
    //在resolve和load阶段 只要我们匹配到相应的值就return 对于路径的处理就完成了 比如对.css bare 相对路径的处理 load获取code值，我们获取到code值后 这个load也就中断了 也就是一种id和一种load 只有一个对应的值 只有在transform阶段 通过continue实现多个插件重复处理一个code代码 我们日常看到的resolve和load主要用于处理得到一个值 一般来讲 就是虚拟模块xx：xx的形式 load是没有匹配的
    async load(id) {
      debugger
      const ctx = new Context() as any;
      for (const plugin of plugins) {
        if (plugin.load) {
          const result = await plugin.load.call(ctx, id);
          if (result) {
            return result
          }
        }
      }
    },
    async transform(code, id) {
      const ctx = new Context() as any;
      for (const plugin of plugins) {
        const result = await plugin.transform?.call(ctx, code, id);
        if (!result) continue
        if (typeof result === "string") {
          code = result;
        } else if (result.code) {
          code = result.code;
        }
      }
      return { code }
    }
  }
  return pluginContainer
}